package cn.xw.utils.security.rsa;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.net.URL;
import java.util.Objects;

/**
 * 测试和使用上面的RSA工具的示例
 *
 * @author Anhui AntLaddie（博客园蚂蚁小哥）
 * @version 1.0
 **/
public class SampleRSACodeDemo {

    /*
    方法总览说明：
        KeyPairUtils类：生成
            generateKeyPair方法：生成公钥、密钥、数字证书、密钥库

        BaseParsing类：解析
            certificateWhetherOverdue方法：校验证书是否过期
            analysisKeystorePrivateKey方法：根据传入的密钥库流信息解析密钥库内的指定别名的私钥信息
            analysisKeystoreCertificates方法：根据传入的密钥库流信息解析密钥库内的全部证书
            certificateParsing方法：证书解析
            publicKeyParsing方法：根据传入的公钥信息流对象进行解析，返回具体的Base64格式公钥；（这里以我生成的公钥来解析）
            privateKeyParsing方法：根据传入的私钥信息流对象进行解析，返回具体的Base64格式私钥；（这里以我生成的私钥来解析）
            certificateVerificationTime方法：校验证书信息是否过期

        EncryptAndDecryptUtils类：加密解密
            keystorePrivateKeyDecrypt方法：根据密钥库内的私钥对密文进行解析，
            certificatePublicKeyEncrypt方法：根据传入的证书信息，对明文进行加密
            simplePublicKeyEncrypt方法：简答加密（根据Base64的公钥字符串进行加密）
            simplePrivateKeyDecrypt方法：简答解密（根据Base64的私钥字符串进行解密）
     */
    public static void main(String[] args) throws Exception {
        // 构建rsa密钥公钥和证书
        //generateKeyPair();
        // 解析证书
        //parseCertificate();
        // 加密解密
        encryptionAndDecryption();
    }

    /***
     * 生成标准的数字证书和公钥私钥
     */
    public static void generateKeyPair() {
        // 构建创建信息，主要参考RSAProperties类的配置，若不写则默认，（这里我只设置自签名证书的基本信息）
        RSAProperties rsaProperties = new RSAProperties();
        //rsaProperties.setSimpleGeneration(false);
        rsaProperties.setCertificateInfo("中华人民共和国", "浙江省", "杭州市",
                "大哥科技有限公司", "研发部", "小哥分公司");
        // 生成证书
        KeyPairUtils keyPairUtils = new KeyPairUtils(rsaProperties);
        keyPairUtils.generateKeyPair();
        // 如路径和默认生成的文件名称没改则在：./classes/security/rsa/日期年月日时分/生成的文件
        // certificate.p12 密钥库（存放证书和密钥的）
        // digital_certificate.pem 数字证书
        // public_key.pem 公钥
        // private_key.pem 私钥（私钥默认不会生成，而是在密钥库，需要设置 simpleGeneration=false）
    }

    /***
     * 解析数字证书 digital_certificate.pem
     */
    public static void parseCertificate() throws FileNotFoundException {
        // 获取类路径资源(证书)
        URL url = SampleRSACodeDemo.class.getClassLoader()
                .getResource("security/rsa/202306202235/digital_certificate.pem");
        FileInputStream fileInputStream1 = new FileInputStream(Objects.requireNonNull(url).getPath());
        // 解析
        CertificateMessage certificateMessage = BaseParsing.certificateParsing(fileInputStream1);
        System.out.println(certificateMessage);
    }

    /***
     * 加密（获取公钥加密）；解密（是在密钥库内获取私钥后解密）
     */
    public static void encryptionAndDecryption() throws FileNotFoundException {
        String message = "我是个要加密的数据啦啦啦！";
        // 获取类路径资源(公钥)
        URL url = SampleRSACodeDemo.class.getClassLoader()
                .getResource("security/rsa/202306202235/digital_certificate.pem");
        FileInputStream publicKeyStream = new FileInputStream(Objects.requireNonNull(url).getPath());
        // 加密
        String encryption = EncryptAndDecryptUtils.certificatePublicKeyEncrypt(publicKeyStream, message);
        System.out.println("加密后的文本信息：" + encryption);

        // 获取类路径资源(密钥库)
        URL url1 = SampleRSACodeDemo.class.getClassLoader()
                .getResource("security/rsa/202306202235/certificate.p12");
        FileInputStream certificateStream = new FileInputStream(Objects.requireNonNull(url1).getPath());
        // 解密
        String decryption = EncryptAndDecryptUtils.keystorePrivateKeyDecrypt(certificateStream,
                "PKCS12", "##ED12^a*8(&E6^PR", "h3J^*a#12@Klp$%z",
                "myPrivateKeyAlias", encryption);
        System.out.println("解密后的数据：" + decryption);
    }
}
